home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / progtool / c / gcc / gempp19.zoo / gem++19 / src / gemw.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-02  |  23.4 KB  |  1,121 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. //  This file is Copyright 1992,1993 by Warwick W. Allison.
  4. //  This file is part of the gem++ library.
  5. //  You are free to copy and modify these sources, provided you acknowledge
  6. //  the origin by retaining this notice, and adhere to the conditions
  7. //  described in the file COPYING.LIB.
  8. //
  9. //  (Extensions made in 1992 by Andre Pareis.)
  10. //
  11. /////////////////////////////////////////////////////////////////////////////
  12.  
  13. #include <aesbind.h>
  14. #include <bool.h>
  15. #include "gema.h"
  16. #include "gemw.h"
  17. #include "gemf.h"
  18. #include "vdi.h"
  19. #include "contract.h"
  20.  
  21. #ifndef WF_BEVENT
  22. #define WF_BEVENT 24
  23. #endif
  24.  
  25. #ifndef WF_BOTTOM
  26. #define WF_BOTTOM 25
  27. #endif
  28.  
  29. static int abs(int i)
  30. {
  31.     return i<0 ? -i : i;
  32. }
  33.  
  34. // Defining STOP_WINX prevents windows from moving off the left edge
  35. // of the screen (The WINX extensions allow this in GEM).
  36. // #define STOP_WINX
  37.  
  38. extern "C" { int __aes__(unsigned long coded_control); }
  39.  
  40. void wind_get_dcol(int part, int* w1, int* w2)
  41. // Since gemlib doesn't support it.
  42. {
  43.     _intin[0]=0;
  44.     _intin[1]=WF_DCOLOR;
  45.     _intin[2]=part;
  46.  
  47.     __aes__(0x68030400);
  48.  
  49.     *w1 = _intout[2];
  50.     *w2 = _intout[3];
  51. }
  52.  
  53. // Maximum number of colour that we will remember.
  54. // There are only 19 possible ones (... currently).
  55. const int MAXPARTCOL=18;
  56.  
  57. // Colours of parts are stored in these records.
  58. class GEMwPartCol {
  59. public:
  60.     short active_col, inactive_col;
  61. };
  62.  
  63.  
  64. ////////////////////////////////////////
  65. //    constructors, destructor
  66. ////////////////////////////////////////
  67.  
  68. GEMwindow::GEMwindow(GEMactivity& in, int Parts) :
  69.     parts(Parts),
  70.     xoff(0), yoff(0),
  71.     opened(FALSE), created(FALSE), initialized(FALSE),
  72.     xalign(1), yalign(1),
  73.     act(0),
  74.     partcol(0),
  75.     bevent(0)
  76. {
  77.     Pos = Max = GRect(0, 0, 0, 0);
  78.     *(info = new char[1]) = 0;    // create an empty string
  79.     *(name = new char[1]) = 0;        // create an empty name
  80.  
  81.     lineHeight = 1;
  82.     columnWidth = 1;
  83.  
  84.     if (parts<0) {
  85.         handle = 0;
  86.         Create();
  87.     }
  88.  
  89.     InActivity(in);
  90. }
  91.  
  92.  
  93. GEMwindow::GEMwindow(GEMactivity& in, int Parts, const GRect& actWorkArea, const GRect& maxWorkArea) :
  94.     parts(Parts),
  95.     Pos(actWorkArea), Max(maxWorkArea), handle(0),
  96.     opened(FALSE), created(FALSE), initialized(TRUE),
  97.     xoff(0), yoff(0),
  98.     xalign(1), yalign(1),
  99.     act(0),
  100.     partcol(0),
  101.     bevent(0)
  102. {
  103.     *(info = new char[1]) = 0;    // create an empty string
  104.     *(name = new char[1]) = 0;        // create an empty name
  105.  
  106.     lineHeight = 1;
  107.     columnWidth = 1;
  108.  
  109.     if (parts<0) {
  110.         handle = 0;
  111.         Create();
  112.     }
  113.  
  114.     InActivity(in);
  115. }
  116.  
  117.  
  118. GEMwindow::GEMwindow(GEMactivity& in, int Parts, const GRect& workArea) :
  119.     parts(Parts),
  120.     Pos(workArea), Max(workArea), handle(0),
  121.     opened(FALSE), created(FALSE), initialized(TRUE),
  122.     xoff(0), yoff(0),
  123.     xalign(1), yalign(1),
  124.     act(0),
  125.     partcol(0),
  126.     bevent(0)
  127. {
  128.     *(info = new char[1]) = 0;    // create an empty string
  129.     *(name = new char[1]) = 0;        // create an empty name
  130.  
  131.     lineHeight = 1;
  132.     columnWidth = 1;
  133.  
  134.     if (parts<0) {
  135.         handle = 0;
  136.         Create();
  137.     }
  138.  
  139.     InActivity(in);
  140. }
  141.  
  142. GEMwindow::GEMwindow(const GEMwindow& copy) :
  143.     parts(copy.parts), Pos(copy.Pos), Max(copy.Max),
  144.     handle(0), opened(FALSE), created(FALSE),
  145.     initialized(copy.initialized),
  146.     xoff(copy.xoff), yoff(copy.yoff),
  147.     xalign(copy.xalign), yalign(copy.yalign),
  148.     info(strdup(copy.info)),
  149.     name(strdup(copy.name)),
  150.     act(0),
  151.     storer(copy.storer),
  152.     vSize(copy.vSize), vPosition(copy.vSize),
  153.     hSize(copy.vSize), hPosition(copy.vSize),
  154.     lineHeight(copy.lineHeight),
  155.     columnWidth(copy.columnWidth),
  156.     partcol(0),
  157.     bevent(copy.bevent)
  158. {
  159.     if (copy.partcol) {
  160.         for (int i=0; i<=MAXPARTCOL; i++) {
  161.             if (copy.partcol[i].active_col!=-1 || copy.partcol[i].inactive_col!=-1)
  162.                 SetPartColour(i,
  163.                     copy.partcol[i].active_col,
  164.                     copy.partcol[i].inactive_col);
  165.         }
  166.     }
  167.  
  168.     GRect win=BorderRect();
  169.     win.g_x+=10;
  170.     win.g_y+=10;
  171.     Move(win.g_x,win.g_y);
  172.  
  173.     // If the original window was in an activity, put this one in there too.
  174.     if (copy.act) InActivity(*copy.act);
  175. }
  176.  
  177. GEMwindow::~GEMwindow()
  178. {
  179.     if (act) act->RemoveWindow(*this);
  180.  
  181.     if (IsOpen())
  182.         Close();
  183.  
  184.     if (IsCreated())
  185.         Delete();
  186.     
  187.     delete info;
  188.     delete name;
  189.     delete [] partcol;
  190.  
  191.     Ensure(!IsCreated());
  192. }
  193.  
  194.  
  195. void GEMwindow::RedrawOverlaps(const GRect& area)
  196. // Standard algorithm found in all GEM code... that's why we have classes!
  197. {
  198.     GRect box,
  199.         dirty_dest,
  200.         work_area = WorkRect();
  201.  
  202.     wind_update(BEG_UPDATE);
  203.     graf_mouse(M_OFF, 0);
  204.  
  205.     wind_get(handle, WF_FIRSTXYWH, &box.g_x, &box.g_y, &box.g_w, &box.g_h);
  206.  
  207.     while (box.g_w && box.g_h)
  208.     {
  209.         if (rc_intersect(&(GRect&)area, &box))
  210.         {
  211.             rc_copy(&box, &dirty_dest);
  212.             
  213.             if (rc_intersect(&work_area, &dirty_dest))
  214.                 Redraw(dirty_dest);
  215.         }
  216.         wind_get(handle, WF_NEXTXYWH, &box.g_x, &box.g_y, &box.g_w, &box.g_h);
  217.     }
  218.     
  219.     graf_mouse(M_ON, 0);
  220.     wind_update(END_UPDATE);
  221. }
  222.  
  223.  
  224. ////////////////////////////////////////////////////////////////////////
  225. //
  226. // SPC:    Redraw(GRect& area)
  227. //    -- this method should be redefined in client classes
  228. //
  229. ////////////////////////////////////////////////////////////////////////
  230.  
  231. void GEMwindow::Redraw(const GRect& area)
  232. {
  233.     // clients should clip the 'area' and draw the window contents
  234. }
  235.  
  236. void GEMwindow::Open()
  237. {
  238.     if (!IsOpen()) {
  239.         Create();
  240.         if (!IsCreated()) return;
  241.  
  242.         VFlushSlider();
  243.         HFlushSlider();
  244.         wind_set(handle, WF_NAME, name, 0, 0);
  245.         wind_set(handle, WF_INFO, info, 0, 0);
  246.  
  247.         GRect    win = BorderRect();
  248.  
  249.         wind_open(handle, win.g_x, win.g_y, win.g_w, win.g_h);
  250.         opened = TRUE;
  251.     } else {
  252.         wind_set(handle, WF_TOP);
  253.     }
  254.  
  255.     if (act) act->Topped(*this);
  256.  
  257.     Ensure(IsOpen());
  258. }
  259.  
  260. void GEMwindow::Close()
  261. {
  262.     if (IsOpen() && handle) {
  263.         wind_close(handle);
  264.         opened = FALSE;
  265.         act->Bottomed(*this);
  266.         Delete();
  267.     }
  268. }
  269.  
  270.  
  271. ////////////////////////////////////////////////////////////////////////
  272. //
  273. // SPC:    move(int x, int y)
  274. //    -- Move() moves the window to the upper left point (x, y) and
  275. //    -- performs the move at screen if the window is opened
  276. //
  277. ////////////////////////////////////////////////////////////////////////
  278.  
  279. void GEMwindow::Move(int x, int y)
  280. {
  281.     GRect    win = BorderRect();
  282.     GRect    root;
  283.  
  284.     win.MoveAbs((x+xoff+xalign/2)/xalign*xalign-xoff,
  285.         (y+yoff+yalign/2)/yalign*yalign-yoff);
  286.     
  287.     wind_get(0, WF_WORKXYWH, &root.g_x, &root.g_y, &root.g_w, &root.g_h);
  288.  
  289. #ifdef STOP_WINX
  290.     if (win.g_x < root.g_x)
  291.         win.g_x = root.g_x;
  292.     if (win.g_y < root.g_y)
  293.         win.g_y = root.g_y;
  294. #endif
  295.  
  296.     SetBorderRect(win);
  297. }
  298.  
  299. void GEMwindow::Top(const GEMevent&)
  300. {
  301.     if (handle && IsOpen()) {
  302.         wind_set(handle, WF_TOP);
  303.         act->Topped(*this);
  304.     }
  305. }
  306.  
  307. void GEMwindow::Bottom(const GEMevent&)
  308. {
  309.     if (handle && IsOpen()) {
  310.         wind_set(handle, WF_BOTTOM);
  311.         act->Bottomed(*this);
  312.     }
  313. }
  314.  
  315. GEMfeedback GEMwindow::Click(const GEMevent&)
  316. {
  317.     return ContinueInteraction;
  318. }
  319.  
  320.  
  321. void GEMwindow::Align(int x, int y, int xmult=8, int ymult=1)
  322. {
  323.     xoff=x;
  324.     yoff=y;
  325.  
  326.     // Ignore 0 multiples!
  327.     if (xmult) xalign=xmult;
  328.     if (ymult) yalign=ymult;
  329. }
  330.  
  331. void GEMwindow::InActivity(GEMactivity& in)
  332. {
  333.     in.AddWindow(*this);
  334.     act=∈
  335. }
  336.  
  337.  
  338. ////////////////////////////////////////////////////////////////////////
  339. //
  340. //    Here are the extensions added by A.Pareis, and subsequently greatly
  341. //  edited by Warwick.
  342. //
  343. ////////////////////////////////////////////////////////////////////////
  344.  
  345.  
  346.  
  347. ////////////////////////////////////////////////////////////////////////
  348. //
  349. // SPC:    Create()
  350. //    -- Create() creates the real window how GEM knows it;
  351. //    -- the returned value signals the success of the operation
  352. //
  353. ////////////////////////////////////////////////////////////////////////
  354.  
  355. bool GEMwindow::Create()
  356. {
  357.     Require(!IsCreated());
  358.     if (IsCreated()) return FALSE;
  359.     
  360.     GRect win;
  361.     
  362.     if (!initialized) {
  363.         // i.e., no rectangles given
  364.         wind_get(0, WF_WORKXYWH, &win.g_x, &win.g_y, &win.g_w, &win.g_h);
  365.         Pos = Max = Win2Work(win);
  366.         initialized = TRUE;
  367.     } else
  368.         win = BorderRect();
  369.  
  370.     if (parts<0) {
  371.         handle=0; // ie. Desktop
  372.         parts=0;
  373.     } else {
  374.         handle = wind_create(parts, win.g_x, win.g_y, win.g_w, win.g_h);
  375.     }
  376.     
  377.     if (handle>=0) {
  378.         // if succesfully created
  379.         created = TRUE;
  380.         if (partcol) {
  381.             for (int i=0; i<=MAXPARTCOL; i++) {
  382.                 if (partcol[i].active_col!=-1 || partcol[i].inactive_col!=-1)
  383.                     wind_set(handle,WF_COLOR,i,partcol[i].active_col,partcol[i].inactive_col,0);
  384.             }
  385.         }
  386.         wind_set(handle,WF_BEVENT,bevent,0,0,0);
  387.     }
  388.     
  389.     return created;
  390. }
  391.  
  392.  
  393.  
  394.  
  395. ////////////////////////////////////////////////////////////////////////
  396. //
  397. // SPC:    Delete()
  398. //    -- delete the real GEM window, but not the instance of this class
  399. //    -- if the window is opened, close it first
  400. //
  401. ////////////////////////////////////////////////////////////////////////
  402.  
  403. void GEMwindow::Delete()
  404. {
  405.     if (IsCreated()) {
  406.         if (IsOpen())
  407.             Close();
  408.  
  409.         if (handle) wind_delete(handle);
  410.         created = FALSE;
  411.     
  412.         Ensure(!IsCreated());
  413.     }
  414. }
  415.  
  416.  
  417.  
  418.  
  419.  
  420. ////////////////////////////////////////////////////////////////////////
  421. //
  422. // SPC:    BecomeDeleted()
  423. //
  424. ////////////////////////////////////////////////////////////////////////
  425.  
  426. void GEMwindow::BecomeDeleted()
  427. {
  428.     if (IsCreated()) {
  429.         opened = FALSE;
  430.         created = FALSE;
  431.     
  432.         Ensure(!IsCreated());
  433.     }
  434. }
  435.  
  436.  
  437.  
  438.  
  439.  
  440. ////////////////////////////////////////////////////////////////////////
  441. //
  442. // SPC:    SetBorderRect(GRect& newPos)
  443. //    -- the window may be moved and resized, if it is opened, the
  444. //    -- action will be performed at screen, too
  445. //
  446. ////////////////////////////////////////////////////////////////////////
  447.  
  448. void GEMwindow::SetBorderRect(const GRect& newPos)
  449. {
  450.     SetWorkRect(Win2Work(newPos));
  451. }
  452.  
  453.  
  454.  
  455. void GEMwindow::SetWorkRect(const GRect& newPos)
  456. {
  457.     Pos = newPos;
  458.  
  459.     if (parts&HSLIDE && Pos.g_w/columnWidth > TotalColumns())
  460.         Pos.g_w=columnWidth * TotalColumns();
  461.  
  462.     if (parts&VSLIDE && Pos.g_h/lineHeight > TotalLines())
  463.         Pos.g_h=lineHeight * TotalLines();
  464.  
  465.     // Round size down to nearest document unit
  466.     Pos.g_w-=Pos.g_w%columnWidth;
  467.     Pos.g_h-=Pos.g_h%lineHeight;
  468.  
  469.     GRect win = BorderRect();
  470.  
  471.     if (IsOpen() && handle)
  472.         wind_set(handle, WF_CURRXYWH, win.g_x, win.g_y, win.g_w, win.g_h);
  473.  
  474.     if (parts&HSLIDE && Pos.g_w/columnWidth != VisibleColumns())
  475.         SetVisibleColumns(Pos.g_w/columnWidth);
  476.  
  477.     if (parts&VSLIDE && Pos.g_h/lineHeight != VisibleLines())
  478.         SetVisibleLines(Pos.g_h/lineHeight);
  479. }
  480.  
  481.  
  482.  
  483.  
  484.  
  485.  
  486. ////////////////////////////////////////////////////////////////////////
  487. //
  488. // SPC:    Resize(int w, int h)
  489. //
  490. ////////////////////////////////////////////////////////////////////////
  491.  
  492. void GEMwindow::Resize(int w, int h)
  493. {
  494.     GRect    win = BorderRect();
  495.     
  496.     win.Resize(w, h);
  497.  
  498.     SetBorderRect(win);
  499. }
  500.  
  501.  
  502.  
  503.  
  504.  
  505.  
  506. GRect GEMwindow::Win2Work(const GRect& outer) const
  507. {
  508.     GRect    tmp;
  509.     
  510.     wind_calc(WC_WORK, parts < 0 ? 0 : parts, outer.g_x, outer.g_y, outer.g_w, outer.g_h,
  511.             &tmp.g_x, &tmp.g_y, &tmp.g_w, &tmp.g_h);
  512.     
  513.     return tmp;
  514. }
  515.  
  516.  
  517. GRect GEMwindow::Work2Win(const GRect& work) const
  518. {
  519.     GRect    tmp;
  520.     
  521.     wind_calc(WC_BORDER, parts < 0 ? 0 : parts, work.g_x, work.g_y, work.g_w, work.g_h,
  522.             &tmp.g_x, &tmp.g_y, &tmp.g_w, &tmp.g_h);
  523.     
  524.     return tmp;
  525. }
  526.  
  527.  
  528. ////////////////////////////////////////////////////////////////////////
  529. //
  530. // SPC:    SetInfoText(const char *line)
  531. //    -- store and set the new info line for the window
  532. //    -- this _must_! be at least created
  533. //
  534. ////////////////////////////////////////////////////////////////////////
  535.  
  536. void GEMwindow::SetInfoText(const char *line)
  537. {
  538.     if (handle) {
  539.         delete info;
  540.         info = new char[ strlen(line)+1 ];
  541.         info = strcpy(info, line);
  542.         if (IsCreated()) wind_set(handle, WF_INFO, info, 0, 0);
  543.  
  544.         Ensure(strcmp(info, line)==0);
  545.     }
  546. }
  547.  
  548.  
  549.  
  550.  
  551.  
  552.  
  553.  
  554. GEMfeedback GEMwindow::UserClosed()
  555. {
  556.     Close();
  557.     return ContinueInteraction;
  558. }
  559.  
  560.  
  561. ////////////////////////////////////////////////////////////////////////
  562. //
  563. // SPC:    UserFulled()
  564. //    -- usually called by an application manager, the default action
  565. //    -- is to toggle between two possible positions and sizes
  566. //
  567. ////////////////////////////////////////////////////////////////////////
  568.  
  569. void GEMwindow::UserFulled()
  570. {
  571.     Require(IsOpen());
  572.     if (!IsOpen()) return;
  573.     
  574.     if (Max==WorkRect())            // i.e., is fulled
  575.         SetWorkRect(storer);        // use stored value
  576.     else
  577.     {
  578.         storer = WorkRect();        // store actual rectangle
  579.         SetWorkRect(Max);
  580.     }
  581. }
  582.  
  583.  
  584.  
  585.  
  586. ////////////////////////////////////////////////////////////////////////
  587. //
  588. // SPC:    UserResized(int w, int h)
  589. //    -- this function may be redefined to align the new size, but
  590. //    -- here it does nothing else than to call the standard Resize()
  591. //    -- of a simple GEMwindow with the same values
  592. //
  593. ////////////////////////////////////////////////////////////////////////
  594.  
  595. void GEMwindow::UserResized(int w, int h)
  596. {
  597.     Resize(w, h);
  598. }
  599.  
  600. void GEMwindow::UserMoved(int x, int y)
  601. {
  602.     Move(x, y);
  603. }
  604.  
  605.  
  606. void GEMwindow::SetName(const char *newName)
  607. {    
  608.     delete name;
  609.     name = new char[ strlen(newName)+1 ];
  610.     name = strcpy(name, newName);
  611.     if (IsCreated())
  612.         wind_set(handle, WF_NAME, name, 0, 0);
  613. }
  614.  
  615.  
  616. ////////////////////////////////////////////////////////////////////////
  617. //
  618. // SPC:    Flush()
  619. //    -- this method will be called, if the user changed the state
  620. //    -- of a slider, e.g., by moving it; descendant classes may
  621. //    -- refine it, with the aim of a more efficient implementation
  622. //
  623. ////////////////////////////////////////////////////////////////////////
  624.  
  625. void GEMwindow::Flush()
  626. {
  627.     if (IsOpen())
  628.         RedrawOverlaps(WorkRect());
  629. }
  630.  
  631.  
  632. ////////////////////////////////////////////////////////////////////////
  633. //
  634. // SPC:    SetVisibleLines(int noOfLines)
  635. //    -- change the number of visible lines, this change will be
  636. //    -- flushed through to the GEM window
  637. //
  638. ////////////////////////////////////////////////////////////////////////
  639.  
  640. void GEMwindow::SetVisibleLines(int noOfLines)
  641. {
  642.     GEMpanarea::SetVisibleLines(noOfLines);
  643.  
  644.     VFlushSlider();
  645. }
  646.  
  647.  
  648. void GEMwindow::SetTotalLines(int noOfLines)
  649. {
  650.     if (noOfLines!=TotalLines()) {
  651.         GEMpanarea::SetTotalLines(noOfLines);
  652.  
  653.         VFlushSlider();
  654.  
  655.         Flush();
  656.     }
  657. }
  658.  
  659. void GEMwindow::SetTopLine(int noOfLine)
  660. {
  661.     int prev_topline=TopLine();
  662.  
  663.     GEMpanarea::SetTopLine(noOfLine);
  664.  
  665.     if (TopLine()!=prev_topline) {
  666.         VFlushSlider();
  667.  
  668.         if (abs(noOfLine-prev_topline) < VisibleLines() && ScrollByBlitting()) {
  669.             int pixels_down=(noOfLine-prev_topline)*LineHeight();
  670.  
  671.             GRect box,
  672.                 clip,
  673.                 work_area = WorkRect();
  674.  
  675.             wind_update(BEG_UPDATE);
  676.             graf_mouse(M_OFF, 0);
  677.             VDI vdi;
  678.  
  679.             wind_get(handle, WF_FIRSTXYWH, &box.g_x, &box.g_y, &box.g_w, &box.g_h);
  680.  
  681.             while (box.g_w && box.g_h)
  682.             {
  683.                 rc_copy(&box, &clip);
  684.                 
  685.                 if (rc_intersect(&work_area, &clip)) {
  686.                     if (clip.g_h > abs(pixels_down)) {
  687.                         int pxy[8];
  688.  
  689.                         pxy[0]=clip.g_x;
  690.                         pxy[2]=clip.g_x+clip.g_w-1;
  691.                         pxy[4]=clip.g_x;
  692.                         pxy[6]=clip.g_x+clip.g_w-1;
  693.  
  694.                         if (pixels_down>0) {
  695.                             pxy[1]=clip.g_y+pixels_down;
  696.                             pxy[3]=clip.g_y+clip.g_h-1;
  697.                             pxy[5]=clip.g_y;
  698.                             pxy[7]=clip.g_y+clip.g_h-pixels_down-1;
  699.                         } else {
  700.                             pxy[1]=clip.g_y;
  701.                             pxy[3]=clip.g_y+clip.g_h+pixels_down-1;
  702.                             pxy[5]=clip.g_y-pixels_down;
  703.                             pxy[7]=clip.g_y+clip.g_h-1;
  704.                         }
  705.  
  706.                         vdi.ro_cpyfm(VDI::SRC,pxy);
  707.                     }
  708.  
  709.                     if (pixels_down>0) {
  710.                         GRect redraw_side(clip.g_x,clip.g_y+clip.g_h-pixels_down,
  711.                             clip.g_w,pixels_down);
  712.                         if (rc_intersect(&work_area,&redraw_side))
  713.                             Redraw(redraw_side);
  714.                     } else {
  715.                         GRect redraw_side(clip.g_x,clip.g_y,clip.g_w,-pixels_down);
  716.                         if (rc_intersect(&work_area,&redraw_side))
  717.                             Redraw(redraw_side);
  718.                     }
  719.                 }
  720.  
  721.                 wind_get(handle, WF_NEXTXYWH, &box.g_x, &box.g_y, &box.g_w, &box.g_h);
  722.             }
  723.         
  724.             graf_mouse(M_ON, 0);
  725.             wind_update(END_UPDATE);
  726.         } else {
  727.             Flush();
  728.         }
  729.     }
  730. }
  731.  
  732.  
  733.  
  734.  
  735. ////////////////////////////////////////////////////////////////////////
  736. //
  737. // SPC:    VCalculateGEMvalues() and CalculateValues():
  738. //    -- use the members totalLines, visibleLines and
  739. //    -- actualTopLine to calculate the size and position of the GEM
  740. //    -- slider and vice versa;
  741. //
  742. ////////////////////////////////////////////////////////////////////////
  743.  
  744. void GEMwindow::VCalculateGEMvalues()
  745. {
  746.     if (TotalLines() > 0) {
  747.         vSize = 1000 * VisibleLines() / TotalLines();
  748.  
  749.         if (TotalLines() == VisibleLines())
  750.             vPosition = 1;
  751.         else
  752.             vPosition = TopLine() * 1000 /
  753.                 (TotalLines()-VisibleLines());
  754.     }
  755. }
  756.  
  757.  
  758.  
  759.  
  760. ////////////////////////////////////////////////////////////////////////
  761. //
  762. // SPC: VCalculateValues()
  763. //    -- that method converts the GEM representation of the slider
  764. //    -- into the document representation
  765. //
  766. ////////////////////////////////////////////////////////////////////////
  767.  
  768. void GEMwindow::VCalculateValues()
  769. {
  770.     SetTopLine(vPosition*(TotalLines()-VisibleLines())/1000);
  771. }
  772.  
  773.  
  774.  
  775.  
  776.  
  777.  
  778. ////////////////////////////////////////////////////////////////////////
  779. //
  780. // SPC:    VFlushSlider()
  781. //    -- is the counterpart of Flush(),
  782. //    -- and is used to flush any changes in the internal slider
  783. //    -- representation through to GEM; it doesn't need to be redefined
  784. //
  785. ////////////////////////////////////////////////////////////////////////
  786.  
  787. void GEMwindow::VFlushSlider()
  788. {
  789.     if (handle) {
  790.         VCalculateGEMvalues();            // ensures correctness
  791.     
  792.         if (IsCreated()) {
  793.             wind_set(handle, WF_VSLIDE, vPosition, 0, 0, 0);
  794.             wind_set(handle, WF_VSLSIZE, vSize, 0, 0, 0);
  795.         }
  796.     }
  797. }
  798.  
  799.  
  800.  
  801.  
  802.  
  803.  
  804.  
  805.  
  806. ////////////////////////////////////////////////////////////////////////
  807. //
  808. // SPC:    VSlidered(int newPos)
  809. //    -- this function is called by the application manager, if
  810. //    -- the user has moved the vertical slide box to a new position;
  811. //    -- the default action performed by it is to store the new value,
  812. //    -- then to call VCalculateValues(), and then to return
  813. //    -- the value RedrawMe to the caller
  814. //
  815. ////////////////////////////////////////////////////////////////////////
  816.  
  817. void GEMwindow::VSlidered(int newPos)
  818. {
  819.     vPosition = newPos;
  820.     
  821.     VCalculateValues();
  822. }
  823.  
  824.  
  825.  
  826.  
  827.  
  828. ////////////////////////////////////////////////////////////////////////
  829. //
  830. // SPC:    SetVisibleColumns(int noOfLines)
  831. //    -- change the number of visible columns, this change will be
  832. //    -- flushed through to the GEM window
  833. //
  834. ////////////////////////////////////////////////////////////////////////
  835.  
  836. void GEMwindow::SetVisibleColumns(int noOfColumns)
  837. {
  838.     GEMpanarea::SetVisibleColumns(noOfColumns);
  839.     
  840.     HFlushSlider();
  841. }
  842.  
  843.  
  844.  
  845. void GEMwindow::SetTotalColumns(int noOfColumns)
  846. {
  847.     if (noOfColumns!=TotalColumns()) {
  848.         GEMpanarea::SetTotalColumns(noOfColumns);
  849.         
  850.         HFlushSlider();
  851.         
  852.         Flush();
  853.     }
  854. }
  855.  
  856.  
  857.  
  858.  
  859. void GEMwindow::SetLeftColumn(int noOfColumn)
  860. {
  861.     int prev_leftcolumn=LeftColumn();
  862.  
  863.     GEMpanarea::SetLeftColumn(noOfColumn);
  864.  
  865.     if (LeftColumn()!=prev_leftcolumn) {
  866.         HFlushSlider();
  867.  
  868.         if (abs(noOfColumn-prev_leftcolumn) < VisibleColumns() && ScrollByBlitting()) {
  869.             int pixels_right=(noOfColumn-prev_leftcolumn)*ColumnWidth();
  870.  
  871.             GRect box,
  872.                 clip,
  873.                 work_area = WorkRect();
  874.  
  875.             wind_update(BEG_UPDATE);
  876.             graf_mouse(M_OFF, 0);
  877.             VDI vdi;
  878.  
  879.             wind_get(handle, WF_FIRSTXYWH, &box.g_x, &box.g_y, &box.g_w, &box.g_h);
  880.  
  881.             while (box.g_w && box.g_h)
  882.             {
  883.                 rc_copy(&box, &clip);
  884.                 
  885.                 if (rc_intersect(&work_area, &clip)) {
  886.                     if (clip.g_w > abs(pixels_right)) {
  887.                         int pxy[8];
  888.  
  889.                         if (pixels_right>0) {
  890.                             pxy[0]=clip.g_x+pixels_right;
  891.                             pxy[2]=clip.g_x+clip.g_w-1;
  892.                             pxy[4]=clip.g_x;
  893.                             pxy[6]=clip.g_x+clip.g_w-pixels_right-1;
  894.                         } else {
  895.                             pxy[0]=clip.g_x;
  896.                             pxy[2]=clip.g_x+clip.g_w+pixels_right-1;
  897.                             pxy[4]=clip.g_x-pixels_right;
  898.                             pxy[6]=clip.g_x+clip.g_w-1;
  899.                         }
  900.  
  901.                         pxy[1]=clip.g_y;
  902.                         pxy[3]=clip.g_y+clip.g_h-1;
  903.                         pxy[5]=clip.g_y;
  904.                         pxy[7]=clip.g_y+clip.g_h-1;
  905.  
  906.                         vdi.ro_cpyfm(VDI::SRC,pxy);
  907.                     }
  908.  
  909.                     if (pixels_right>0) {
  910.                         GRect redraw_side(clip.g_x+clip.g_w-pixels_right,clip.g_y,
  911.                             pixels_right,clip.g_h);
  912.                         if (rc_intersect(&work_area,&redraw_side))
  913.                             Redraw(redraw_side);
  914.                     } else if (pixels_right) {
  915.                         GRect redraw_side(clip.g_x,clip.g_y,-pixels_right,clip.g_h);
  916.                         if (rc_intersect(&work_area,&redraw_side))
  917.                             Redraw(redraw_side);
  918.                     }
  919.                 }
  920.  
  921.                 wind_get(handle, WF_NEXTXYWH, &box.g_x, &box.g_y, &box.g_w, &box.g_h);
  922.             }
  923.         
  924.             graf_mouse(M_ON, 0);
  925.             wind_update(END_UPDATE);
  926.         } else {
  927.             Flush();
  928.         }
  929.     }
  930. }
  931.  
  932.  
  933.  
  934.  
  935. ////////////////////////////////////////////////////////////////////////
  936. //
  937. // SPC:    HCalculateGEMvalues() and HCalculateValues():
  938. //    -- use the members totalColumns, visibleColumns and
  939. //    -- actualLeftColumn to calculate the size and position of the GEM
  940. //    -- slider and vice versa;
  941. //
  942. ////////////////////////////////////////////////////////////////////////
  943.  
  944. void GEMwindow::HCalculateGEMvalues()
  945. {
  946.     if (TotalColumns() > 0) {
  947.         hSize = 1000 * VisibleColumns() / TotalColumns();
  948.  
  949.         if (TotalColumns() == VisibleColumns())
  950.             hPosition = 1;
  951.         else
  952.             hPosition = LeftColumn() * 1000 /
  953.                 (TotalColumns()-VisibleColumns());
  954.     }
  955. }
  956.  
  957.  
  958.  
  959.  
  960. ////////////////////////////////////////////////////////////////////////
  961. //
  962. // SPC: HCalculateValues()
  963. //    -- that method converts the GEM representation of the slider
  964. //    -- into the document representation
  965. //
  966. ////////////////////////////////////////////////////////////////////////
  967.  
  968. void GEMwindow::HCalculateValues()
  969. {
  970.     SetLeftColumn(hPosition*(TotalColumns()-VisibleColumns())/1000);
  971. }
  972.  
  973.  
  974.  
  975.  
  976.  
  977.  
  978. ////////////////////////////////////////////////////////////////////////
  979. //
  980. // SPC:    HFlushSlider()
  981. //    -- is the counterpart of GEMwindow::Flush(),
  982. //    -- and is used to flush any changes in the internal slider
  983. //    -- representation through to GEM; it doesn't need to be redefined
  984. //
  985. ////////////////////////////////////////////////////////////////////////
  986.  
  987. void GEMwindow::HFlushSlider()
  988. {
  989.     if (handle) {
  990.         HCalculateGEMvalues();            // ensures correctness
  991.     
  992.         if (IsCreated()) {
  993.             wind_set(handle, WF_HSLIDE, hPosition, 0, 0, 0);
  994.             wind_set(handle, WF_HSLSIZE, hSize, 0, 0, 0);
  995.         }
  996.     }
  997. }
  998.  
  999.  
  1000.  
  1001.  
  1002.  
  1003.  
  1004.  
  1005.  
  1006. ////////////////////////////////////////////////////////////////////////
  1007. //
  1008. // SPC:    HSlidered(int newPos)
  1009. //    -- this function is called by the application manager, if
  1010. //    -- the user has moved the horizontal slide box to a new position;
  1011. //    -- the default action performed by it is to store the new value,
  1012. //    -- then to call HCalculateValues(), then to return the
  1013. //    -- value RedrawMe to the caller
  1014. //
  1015. ////////////////////////////////////////////////////////////////////////
  1016.  
  1017. void GEMwindow::HSlidered(int newPos)
  1018. {
  1019.     hPosition = newPos;
  1020.     
  1021.     HCalculateValues();
  1022. }
  1023.  
  1024.  
  1025.  
  1026.  
  1027.  
  1028. bool GEMwindow::IsOpen() const
  1029. {
  1030.     return created && opened;
  1031. }
  1032.  
  1033.  
  1034. // "Colour" support.
  1035.  
  1036. void GEMwindow::SetPartColour(int part, short enabledcolour, short disabledcolour)
  1037. {
  1038.     Ensure(part>=0 && part<=MAXPARTCOL);
  1039.  
  1040.     if (!partcol) {
  1041.         partcol=new GEMwPartCol[MAXPARTCOL+1];
  1042.         for (int i=0; i<=MAXPARTCOL; i++) {
  1043.             partcol[i].active_col=-1;
  1044.             partcol[i].inactive_col=-1;
  1045.         }
  1046.     }
  1047.  
  1048.     if (enabledcolour!=-1) partcol[part].active_col=enabledcolour;
  1049.     if (disabledcolour!=-1) partcol[part].inactive_col=disabledcolour;
  1050.  
  1051.     if (IsCreated()) {
  1052.         wind_set(handle,WF_COLOR,part,
  1053.             partcol[part].active_col,
  1054.             partcol[part].inactive_col,0);
  1055.     }
  1056. }
  1057.  
  1058. void GEMwindow::DefaultPartColour(int part)
  1059. {
  1060.     if (partcol) {
  1061.         partcol[part].active_col=-1;
  1062.         partcol[part].inactive_col=-1;
  1063.         if (IsCreated()) {
  1064.             int w1,w2;
  1065.             wind_get_dcol(part,&w1,&w2);
  1066.             //wind_get(0,WF_DCOLOR,&part,&w1,&w2,&j);
  1067.             wind_set(handle,WF_COLOR,part,w1,w2,0);
  1068.         }
  1069.     }
  1070. }
  1071.  
  1072. void GEMwindow::SetPartColours(GEMform& enabled, GEMform& disabled)
  1073. {
  1074.     for (int i=0; i<=MAXPARTCOL; i++) {
  1075.         SetPartColour(i,
  1076.             enabled[i].ObjectSpecific()&0xffff,
  1077.             disabled[i].ObjectSpecific()&0xffff
  1078.         );
  1079.     }
  1080. }
  1081.  
  1082. void GEMwindow::DefaultPartColours()
  1083. {
  1084.     for (int i=0; i<MAXPARTCOL; i++) {
  1085.         DefaultPartColour(i);
  1086.     }
  1087.     delete [] partcol;
  1088.     partcol=0;
  1089. }
  1090.  
  1091. short GEMwindow::PartColour(int part, bool activecolour) const
  1092. {
  1093.     if (activecolour) {
  1094.         if (partcol && partcol[part].active_col!=-1) {
  1095.             return partcol[part].active_col;
  1096.         } else {
  1097.             int w1=0,w2;
  1098.             wind_get_dcol(part,&w1,&w2);
  1099.             //wind_get(0,WF_DCOLOR,&part,&w1,&w2,&j);
  1100.             return w1;
  1101.         }
  1102.     } else {
  1103.         if (partcol && partcol[part].inactive_col!=-1) {
  1104.             return partcol[part].inactive_col;
  1105.         } else {
  1106.             int w1,w2=0;
  1107.             wind_get_dcol(part,&w1,&w2);
  1108.             //wind_get(0,WF_DCOLOR,&part,&w1,&w2,&j);
  1109.             return w2;
  1110.         }
  1111.     }
  1112. }
  1113.  
  1114. int GEMwindow::ButtonEventFlags(int flags)
  1115. {
  1116.     int result=bevent;
  1117.     if (flags!=-1) bevent=flags;
  1118.     if (IsCreated()) wind_set(handle,WF_BEVENT,bevent,0,0,0);
  1119.     return result;
  1120. }
  1121.